权限

package com.irhema.shiro;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
/**
* shiroFilterFactoryBean
* 使用@Bean,将getShiroFilterFactoryBean()方法返回的bean对象装入到spring容器中(放入spring环境中)。
* 好让spring知道我们创建了shiroFilterFactoryBean这样一个对象。否则该方法或该 对象将失效,不起作用
/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
//内置有很多过滤器来进行url的拦截
//设置安全管理器,可通过注解@Qualifier查找securityManager的bean并注入
shiroFilterFactoryBean.setSecurityManager(securityManager);
/
*
* 添加shiro内置过滤器,实现权限相关的拦截器
* 常用的过滤器
* anon 全面开放
* authc 需要认证
* page 使用remember me功能才能访问
* perms 得到该资源权限才能访问 授权拦截器
* role 得到角色权限才能访问 授权拦截器
/
Map<String,String> filterMap=new LinkedHashMap<String, String>();
/
*
* 授权配置
/
filterMap.put("/user/add","perms[user:add]"); /
为添加设置权限拦截--数据库中lmj用户有添加权限--/
shiroFilterFactoryBean.setUnauthorizedUrl("/user/unAuth");
filterMap.put("/user/update","perms[user:update]"); /
为更新设置权限拦截--数据库中admin用户有添加权限--/
//filterMap.put("/user/add","authc");
// filterMap.put("/user/update","authc");
/**
* 认证
/
filterMap.put("/index","anon");
filterMap.put("/user/select","anon");
filterMap.put("/user/login","anon");
filterMap.put("/user/
","authc");
//使用通配符 filterMap.put("/page/
","authc"); 让user下面的所有资源都需要认证后才能放行
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
/**
* 自定义shirio默认跳转的登陆页面
/
shiroFilterFactoryBean.setLoginUrl("/user/toLogin");
return shiroFilterFactoryBean;
}
/
*
* 创建defaultsecurityManager
* 可通过@Qualifier注解拿到getRealm()方法返回的bean作为参数传入getDefaultWebSecurityManager()方法中
/
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
//关联realm
securityManager.setRealm(userRealm);
return securityManager;
}
/
*
* 创建realm
* @Bean注解的含义是让该方法返回的对象注入到spring的环境中,(丢进spring容器里),
* 方便被defaultsecurityManager所调用
*/
@Bean(name="userRealm")
public UserRealm getRealm(){
return new UserRealm();
}

/**
 * 配置ShiroDialect,用于Shiro和thymeleaf标签配合使用
 * @return
 */
@Bean
public ShiroDialect shiroDialect(){
    return new ShiroDialect();
}

}
-----------------------------UserRealm ---------------------
package com.irhema.shiro;

import com.irhema.domain.User;
import com.irhema.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

public class UserRealm extends AuthorizingRealm {
@Autowired
UserService userService;
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;
User user=userService.findByName(token.getUsername());
if (user==null){
return null;
}
//这里传的是user对象,不是"user字符串",这样写会报类型转换错误异常SimpleAuthenticationInfo(“user”,user.getPassword(),"");
return new SimpleAuthenticationInfo(user,user.getPassword(),"");
/**
* 无数据库版本
/
/
String name="lmj";
String password="123";
//将传来的参数转为UsernamePasswordToken
UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;
if (!token.getUsername().equals(name)){
return null;
}
//返回AuthenticationInfo的子类SimpleAuthenticationInfo即可
(第一个参数是返回给login的信息,它是一个当事人对象Principal,可以填user,方便传到doGetAuthorizationInfo中,
第二个是从数据库取来的密码
// shiro会自动去做密码是否匹配的判断,第三个参数是shiro的名字,我们可以留空,第二个参数一定要是数据库 的密码)
return new SimpleAuthenticationInfo("",password,"");
*/
}

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    /**
     * 使用AuthorizationInfo接口的子类SimpleAuthorizationInfo
     * 为用户授予user:add添加的权限
     */
    SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
    /**
     * 数据库中取出权限字符串
     */
    Subject subject= SecurityUtils.getSubject();
    /**
     * //Principal包含用户的标识和用户的所属角色的对象---专业术语叫--当事人,委托人 ,拿到当事人对象
     * 它是认证是传过来的,故需要将原来的doGetAuthorizationInfo()方法中的
     * return new SimpleAuthenticationInfo("",user.getPassword(),"");
     *
     * 更改为:
     * return new SimpleAuthenticationInfo("user",user.getPassword(),"");
     */
    User user= (User) subject.getPrincipal();
    User dbUser=userService.findById(user.getId());
    info.addStringPermission(dbUser.getPerms());
    return info;
}

}
-----------------index

Title

登录



4.0.0

org.springframework.boot
spring-boot-starter-parent
2.1.6.RELEASE


com
irhema
0.0.1-SNAPSHOT
irhema
Demo project for Spring Boot

<properties>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.3.2</version>
    </dependency>

   <!-- 相关数据库依赖-->
    <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.17</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.16</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.0.0</version>
    </dependency>
   <!-- thymeleaf对shiro的扩展坐标。即thymeleaf标签对shiro框架的支持-->
    <!-- https://mvnrepository.com/artifact/com.github.theborakompanioni/thymeleaf-extras-shiro -->
    <dependency>
        <groupId>com.github.theborakompanioni</groupId>
        <artifactId>thymeleaf-extras-shiro</artifactId>
        <version>2.0.0</version>
    </dependency>


</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
    <!-- 配置将哪些资源文件(静态文件/模板文件/mapper文件)加载到tomcat输出目录里 -->
    <resources>
        <resource>
            <directory>src/main/java</directory><!--java文件的路径-->
            <includes>
                <include>**/*.java</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.*</include>
            </includes>
        </resource>
    </resources>

</build>

package com.irhema.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Map;

@Controller
@RequestMapping("/user")
public class UserController {
//因为我们使用了springmvc的全局拦截功能,所以使用超链接跳转就不行了。我们需要写controller。
//让它经过controller来进行资源的访问。相当于controller里配置的资源访问路径是springmvc认为合法的
//允许放行的资源路径
@RequestMapping("/add")
public String add(){
return "add";
}
@RequestMapping("/update")
public String update(){
return "update";
}
@RequestMapping("/toLogin")
public String tologin(){
return "login";
}
@RequestMapping("/select")
public String select(Map<String,Object> map){
map.put("msg","hello");
return "select";
}
@RequestMapping("/login")
public String login(String username, String password, Map<String,Object> map){
map.put("msg","登陆成功:"+" "+username+" "+password);
/**
*使用shiro编写认证操作
*/
// todo 获取subject(通过securityUtil拿到subject用户主题)
Subject subject= SecurityUtils.getSubject();

    // todo 封装用户数据(将用户名,密码装进usernamepasstoken对象里面)
    UsernamePasswordToken token=new UsernamePasswordToken(username,password);
    try{
        /**
         * 这里shiro会将login的处理流程交给UserRealm
         * 我们在userRealm的doGetAuthenticationInfo和doGetAuthorizationInfo里写我们的业务逻辑就可以了
         * 只要执行了subject.login(token);方法,它就一定会来到认证逻辑这里 及上面的两个方法
         */
        subject.login(token);
        return "index";
        //无异常,则说明登陆成功
    }catch (UnknownAccountException e){
       // e.printStackTrace();
        //登陆失败,用户名不存在
        map.put("msg","用户名不存在");
        //不加redirect重定向,程序会认为这是一个页面,我们需要的它是一个请求路径
        System.out.println("用户名不存在");
        return "index";
    }catch (IncorrectCredentialsException e){
       map.put("msg","密码错误");
        System.out.println("密码错误");
        return "index";
    }catch (Exception e){
        System.out.println("用户名或密码为空");
        return null;
    }
}
@RequestMapping("/unAuth")
public String unAuth(Map<String,Object> map){
    map.put("msg","请去授权");
    return "unAuth";
}

}

posted @ 2020-11-11 19:18  brc  阅读(108)  评论(0)    收藏  举报