Shiro---强大且易用的Java安全框架(三)

Shiro】

十、Spring Boot整合Shiro实现登录认证

整体项目结构。省略数据访问层相关代码,使用固定数据进行认证。

1、添加依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.13.RELEASE</version>
</parent>
<dependencies>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring-boot-web-starter</artifactId>
        <version>1.4.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <!--mybatis的启动器-->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.1.1</version>
    </dependency>

    <!--数据库的驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.11</version>
    </dependency>
</dependencies>

2、编写配置文件

新建application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/rbac1?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
    username: root
    password: root
shiro:
  loginUrl: /login

3、新建实体类

新建com.bjsxt.pojo.User

public class User {
    private Long id;
    private String username;
    private String password;
    // 省略getter和setter
// 省略构造方法
}

4、编写业务层代码

新建com.bjsxt.service.UserService

public interface AdminService {
    Admin    findOne(String  uname);
}

实现类

@Service
public class AdminServiceImpl implements AdminService {
     @Autowired
    private AdminMapper  adminMapper;
    @Override
    public Admin findOne(String uname) {
        return adminMapper.selectOne(uname);
    }
}

5、自定义Realm

新建com.bjsxt.realm.MyRealm编写认证逻辑

@Component
public class MyRealm extends AuthorizingRealm {
     @Autowired
    private AdminService  adminService;
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String name = authenticationToken.getPrincipal().toString();
        Admin admin = adminService.findOne(name);
        if(admin!=null){
            AuthenticationInfo  info=new SimpleAuthenticationInfo(name,admin.getPwd(), ByteSource.Util.bytes(admin.getSalt()),"sxt");
            
            return   info;
        }
        return null;
    }}

6、编写配置

新建com.bjsxt.config.ShiroConfig,编写配置

@Configuration
public class SApplicationConfig {
    @Autowired
    private   MyRealm  myRealm;

    @Bean
   public DefaultWebSecurityManager  defaultWebSecurityManager(){
       DefaultWebSecurityManager  defaultWebSecurityManager=new DefaultWebSecurityManager();
        HashedCredentialsMatcher  matcher=new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");
        matcher.setHashIterations(3);
        myRealm.setCredentialsMatcher(matcher);     
        defaultWebSecurityManager.setRealm(myRealm);
       return defaultWebSecurityManager;
   }
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {     
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
        definition.addPathDefinition("/doLogin", "anon");
        definition.addPathDefinition("/login", "anon");
        definition.addPathDefinition("/**", "authc");
        return definition;
    }
}

7、编写控制器

新建com.bjsxt.controller.UserController

@Controller
public class AdminController {
    @RequestMapping("/{path}")
    public   String   getUrl(@PathVariable String path){
        System.out.println("iii");
        return  path;
    }

    @RequestMapping("/doLogin")
    public String   login(String  uname,String  pwd){
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(new UsernamePasswordToken(uname,pwd));
            return "main" ;
        } catch (AuthenticationException e) {
            System.out.println("失败");
            return "login";
        }
    }
}

8、编写启动类

新建com.bjsxt.ShiroApplication

@SpringBootApplication
@MapperScan("com.bjsxt.mapper")
public class ShiroApplication {
    public static void main(String[] args) {
        SpringApplication.run(ShiroApplication.class,args);
    }
}

9、编写页面

9.1 编写登录页面

新建templates/login.html

<form action="/doLogin" method="post">
    用户名:<input type="text" name="username"/><br/>
    密码:<input type="password" name="password" /><br/>
    <input type="submit" value="登录"/>
</form>

9.2 编写主页面

新建templates/login.html。页面中虽然编写内容

<body>
   index.html
</body>

十一、凭证匹配器

1、修改ShiroConfig

@Bean
public DefaultWebSecurityManager securityManager() {
    DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
    HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
    hashedCredentialsMatcher.setHashAlgorithmName("md5");
    hashedCredentialsMatcher.setHashIterations(2);
    myRealm.setCredentialsMatcher(hashedCredentialsMatcher);
    manager.setRealm(myRealm);
    return manager;
}

2、修改UserServiceImpl

模拟从数据库查询出来的密码是加密的密码。

此加密数据是”admin”加盐”123”迭代两次加密的结果。

return new User(1L,"admin","6bdae6366c1e46d541eb0ca9547d974c");

3、修改MyRealm

修改MyRealm中doGetAuthenticationInfo方法。把盐添加进去。

AuthenticationInfo info = new SimpleAuthenticationInfo(token.getPrincipal(),user.getPassword(), ByteSource.Util.bytes("123"),user.getUsername());

十二、remember me实现

1、修改ShiroConfig

秘钥长度为16位,使用的时AES加密。

@Configuration
public class ShiroConfig {
    @Autowired
    private MyRealm myRealm;
    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        hashedCredentialsMatcher.setHashIterations(2);
        myRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        manager.setRealm(myRealm);
        manager.setRememberMeManager(rememberMeManager());
        return manager;
    }
    /**
     * cookie 属性设置
     */
    public SimpleCookie rememberMeCookie()
    {
        SimpleCookie cookie = new SimpleCookie("rememberMe");
//        cookie.setDomain(domain);
        cookie.setPath("/");
        cookie.setHttpOnly(true);
        cookie.setMaxAge(30 * 24 * 60 * 60);
        return cookie;
    }

    /**
     * 记住我
     */
    public CookieRememberMeManager rememberMeManager()
    {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        cookieRememberMeManager.setCipherKey(“1234567890987654”);
        return cookieRememberMeManager;
    }
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
        definition.addPathDefinition("/doLogin", "anon");
        definition.addPathDefinition("/logout", "logout");
        definition.addPathDefinition("/**", "user");
        return definition;
    }

    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }
}

2、修改控制器方法

修改控制doLogin方法,在UsernamePasswordToken中添加第三个参数。表示是否启用remember me功能。

此功能应该在页面中添加一个复选框,代码中直接假设用户勾选了复选框

@RequestMapping("/doLogin")
public String showLogin(User user){
    Subject subject = SecurityUtils.getSubject();
    try {
        //添加第三个参数,表示是否启用rememberme功能
        subject.login(new UsernamePasswordToken(user.getUsername(),user.getPassword(),true));
        return "redirect:/showIndex";
    } catch (Exception e) {
        e.printStackTrace();
    }
    return "redirect:/showLogin";
}

十三、退出实现

1、修改配置类

修改ShiroConfig类,添加logout filter 对应的url。

红色部分为新增内容。

2、修改主页面

在index.html页面中添加超链接。跳转到/logout后会由shiro内置filter进行拦截。

<body>
    index.html
    <a href="/logout">退出</a>
</body>

十四、授权

授权就是判断认证用户是否具有指定角色或指定权限。

Shiro可以和JSP整合也可以和Thymeleaf整合,我们讲解SpringBoot的视图技术Thymeleaf整合Shiro。

只要是授权就执行Realm的doGetAuthorizationInfo进行判断,而触发doGetAuthorizationInfo的方式,常用的就两种:

  • (1)在页面中通过shiro:xxxx 属性进行判断
  • (2)在java代码中通过注解@RequiresXXX/config文件中配置

1、thymeleaf中常用属性

需要在html页面中<html>添加属性

<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">

1.1 shiro:user=””

认证通过或已记住的用户。

1.2 shiro:authenticated=””

认证通过的用户。不包含记住的用户。

1.3 shiro:principal

输出认证用户信息。<shiro:principal/>

1.4 shiro:hasRole="admin"

判断是否具有指定角色。

1.5 shiro:lacksRole="admin"

判断是否具有指定角色。

1.6 shiro:hasAllRoles="role1,role2"

判断指定角色用户是否都具有。

1.7 shiro:hasAnyRoles="role1,role2"

只要用户具有其中一个角色就表示判断通过。

1.8 shiro:hasPermission="userInfo:add"

是否具有指定权限。

1.9 shiro:lacksPermission="userInfo:del"

是否不具有指定权限

1.10 shiro:hasAllPermissions="userInfo:view, userInfo:add"

是否全具有指定权限。

1.11 shiro:hasAnyPermissions="userInfo:view, userInfo:del"

只要有其中任何一个权限即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值